<?php
require_once(dirname(__FILE__).DIRECTORY_SEPARATOR.'interfaces.php');
abstract class ContentBaseController extends BackOfficeController
{
    //content type
    private $_contentType;
    //widget
    private $_widget;
    private $_ws;//widget settings
    private $_wl;//current widget layout
    
    static public $forceRenderPartial=false;
    static public $pageWidget=null;
    static public $pageTitle=null;

    /**
    * <pre>
    * $configValue=$widget->configName;
    * </pre>
    * 
    * @param mixed $name
    */
    public function __get($name)
    {
        if(is_array($this->_ws) && isset($this->_ws[$name]))
        {
            if (isset($this->_ws[$name]['value']))
                return $this->_ws[$name]['value'];
            else
                return null;
        }
        elseif(isset($_GET[$name]))
        {
            return $_GET[$name];
        }
        else
            return parent::__get($name);
    }
    
    /**
    * <pre>
    * $this->configName=$configValue;
    * </pre>
    * 
    * @param mixed $name
    */
    public function __set($name,$value)
    {
        if(is_array($this->_ws) && isset($this->_ws[$name]))
        {
            $this->_ws[$name]['value'] = $value;
        }
        else
            parent::__set($name,$value);
    }
    
    public function init()
    {
        if (!self::$forceRenderPartial)
            parent::init();
    }
    
    public function render($view,$data=null,$return=false)
    {
        if (self::$forceRenderPartial)
        {
            if ($return)
                return parent::renderPartial($view,$data,true);
            else
                parent::renderPartial($view,$data,$return);
        }
        else
        {
            if ($return)
                return parent::render($view,$data,$return);
            else
                parent::render($view,$data,$return);
        }
    }
    
    /**
    * save data to page_widget table
    * 
    * @param array()
    */
    protected function updateWidgetSettings($widgetSetting)
    {
        $templateContentId = (int) Yii::app()->request->getParam('template_content_id', 0);
        $widgetSetting = var_export($widgetSetting, true);
        if (is_object(self::$pageWidget))
        {
            $model = PageWidget::model()->findByPk(self::$pageWidget->id);
            if (is_object($model))
            {
                if ($model->widget_settings_id)
                {
                    $criteria = new CDbCriteria;
                    $criteria->compare('widget_settings_id', $model->widget_settings_id);
                    $criteria->compare('id', $model->widget_settings_id, false, 'OR');
                    PageWidget::model()->updateAll(array('widget_settings'=>$widgetSetting), $criteria);
                }
                else
                {
                    $model->saveAttributes(array('widget_settings'=>$widgetSetting));
                }
            }
            return true;
        }
        else
        {
            $pageId = (int) Yii::app()->request->getParam('page_id', 0);
            $pageRevision = (int) Yii::app()->request->getParam('revision_id', 1);
            $container = Yii::app()->request->getParam('container', '');
            $ordering = (int) Yii::app()->request->getParam('ordering', 0);
            $widgetId = 0;
            $model = $this->getWidget();
            if (is_object($model))
                $widgetId = (int) $model->id;
            $contentTypeId = 0;
            $contentType = $this->getContentType();
            if (is_object($contentType))
                $contentTypeId = (int) $contentType->id;
            
            //save data page_widget
            if ($widgetId && $contentTypeId && (($pageId && $pageRevision) || $templateContentId) && !empty($container))
            {
                if ($ordering == 0)
                {
                    $criteria = new CDbCriteria;
                    $criteria->order = 'ordering';
                    $criteria->compare('page_id',$pageId);
                    $criteria->compare('revision_id',$pageRevision);
                    $criteria->compare('template_content_id',$templateContentId);
                    $criteria->compare('container',$container);
                    $model = PageWidget::model()->find($criteria);
                    $ordering = is_object($model) ? $model->ordering+1 : 1;
                }
                $model = new PageWidget;
                $model->attributes = array(
                    'page_id'=>$pageId,
                    'revision_id'=>$pageRevision,
                    'template_content_id'=>$templateContentId,
                    'content_type_id'=>$contentTypeId,
                    'container'=>$container,
                    'widget_id'=>$widgetId,
                    'widget_settings'=>$widgetSetting,
                    'ordering'=>$ordering,
                    'status'=>1,
                    'creation_datetime'=>date('Y-m-d H:i:s'),
                    'last_update'=>date('Y-m-d H:i:s'),
                );
                if ($model->save())
                {
                    //update ordering
                    $criteria = new CDbCriteria;
                    $criteria->compare('page_id', $model->page_id);
                    $criteria->compare('revision_id', $model->revision_id);
                    $criteria->compare('container', $model->container);
                    $criteria->compare('id', '<>'.$model->id);
                    $criteria->compare('ordering', '>='.$model->ordering);
                    PageWidget::model()->updateAll(array('ordering'=>new CDbExpression('ordering+1')), $criteria);
                }
                else
                {
                    Yii::log(CVarDumper::dumpAsString($model->getErrors()), CLogger::LEVEL_ERROR);
                    return false;
                }
                
                //add link widgets of template with linked page
                if ($templateContentId)
                {
                    //find all children template
                    $tplIds = FSM::_run('Cms.templateContent.getChildrenTemplate', array('id'=>$templateContentId))->children;
                    $tplIds = CPropertyValue::ensureArray($tplIds);
                    array_push($tplIds, $templateContentId);
                    $criteria = new CDbCriteria;
                    $criteria->select = array('page_id','id');
                    $criteria->distinct = true;
                    $criteria->addInCondition('template_content_id', $tplIds);
                    $models = PageRevision::model()->findAll($criteria);
                    if (is_array($models) && count($models))
                    {
                        foreach ($models as $linkedPage)
                        {
                            FSM::_run('Cms.templateContent.linkWidgetsToPage', array(
                                'page_id'=>$linkedPage->page_id,
                                'revision_id'=>$linkedPage->id,
                                'template_content_id'=>$templateContentId,
                            ));
                        }
                    }
                }
                return true;
            }
            else
                Yii::log('$widgetId: '.CVarDumper::dumpAsString($widgetId).', $contentTypeId: '.CVarDumper::dumpAsString($contentTypeId).', $pageId: '.
                    CVarDumper::dumpAsString($pageId).', $pageRevision: '.CVarDumper::dumpAsString($pageRevision).', $container: '.$container, CLogger::LEVEL_ERROR);
        }
    }
    
    /**
    * remove data from page_widget table
    * 
    */
    protected function remove($pageWidgetId)
    {
        PageWidget::model()->deleteByPk($pageWidgetId);
    }
    
    /**
    * @return CmsWidget
    */
    public function getWidget()
    {
        if ($this->_widget === null)
        {
            $this->_widget = CmsWidget::model()->findByAttributes(array('path'=>$this->info['path']));
        }
        return $this->_widget;
    }
    
    /**
    * find layout
    * merge default widget settings, layout settings
    * 
    * @return array
    */
    public function getWidgetSettings()
    {
        if ($this->_ws === null)
        {
            //load data from db
            $widget = $this->getWidget();
            $widgetParams = array();
            $widgetSettings = array();
            if (is_object($widget))
            {
                //load widget_settings from page_widget
                if (!is_object(self::$pageWidget) && isset($_GET['page_widget_id']))
                {
                    self::$pageWidget = PageWidget::model()->findByPk($_GET['page_widget_id']);
                }
                if (is_object(self::$pageWidget))
                {
                    if (is_array(self::$pageWidget->widget_settings))
                        $widgetSettings = self::$pageWidget->widget_settings;
                    elseif (is_string(self::$pageWidget->widget_settings))
                        $widgetSettings = $this->evaluateExpression(self::$pageWidget->widget_settings);
                    if (is_array($widgetSettings) && isset($widgetSettings['widget']))
                        $widgetSettings = $widgetSettings['widget'];
                    else
                        $widgetSettings = array();
                }
                else
                    $widgetParams = $widget->params;
            }
            else
                return $this->_ws;
            //merge data
            $defaultConfig = $this->getDefaultConfig();
            if (is_array($defaultConfig))
            {
                //widget_settings of page_widget
                if (is_array($widgetSettings) && count($widgetSettings))
                {
                    foreach ($widgetSettings as $key => $data)
                    {
                        if (isset($defaultConfig[$key]))
                            $defaultConfig[$key]['value'] = $data;
                        else//extra config, not in default widget config
                            $defaultConfig[$key] = array(
                                'value'=>$data,
                                'visible'=>0,
                            );
                    }
                }
                elseif (is_array($widgetParams) && count($widgetParams))
                {
                    foreach ($widgetParams as $widgetParam)
                    {
                        if (isset($defaultConfig[$widgetParam->name]))
                        {
                            $data = array(
                                'label'=>'',
                                'value'=>'',
                                'description'=>'',
                                'setting_group'=>'',
                                'ordering'=>'',
                                'visible'=>'',
                            );
                            $data = array_intersect_key($widgetParam->attributes, $data);
                            $defaultConfig[$widgetParam->name] = CMap::mergeArray($defaultConfig[$widgetParam->name], $data);
                        }
                    }
                }
            }
            $this->_ws = $defaultConfig;
            //init layout
            $this->getWidgetLayout();
        }
        return $this->_ws;
    }
    
    /**
    * 
    * @return array
    * 
    * 'name' => array(
                'type' => CHtml::function or Yii path to a widget. 
                            If CHtml function then the function name is in lower case. 
                            Suffixes like 'field' or 'button' must be removed
                'rules' => array('rule name - see Yii rule classes' => array(config)),
                'items' => array(key => value) //used for dropDownList of similar CHtml functions
                'htmlOptions' => array()
                // following items are used to setup the widget setting info while installing  
                'label'           => 'Short friendly param name'
                'value'           => 'default value'
                'description'     => 'Full description'
                'setting_group'   => 'General Settings'
                'ordering'        => 0
                'visible'         => 0
            ),
    */
    public function getDefaultConfig()
    {
        return array(
            'currentLayout'=>array(
                'label'=>'Layout',
                'value'=>'default',
                'description'=>'Widget Layout',
                'setting_group'=>'General Settings',
                'type'=>'dropdownlist',
                'items'=>array('default'=>'Default'),
                'visible'=>true,
            ),
        );
    }
    
    /**
    * @return WidgetLayoutBase
    */
    public function getWidgetLayout()
    {
        if ($this->_wl === null)
        {
            $className = str_replace('Controller', '', get_class($this)).ucfirst($this->currentLayout).'Layout';
            $criteria = new CDbCriteria;
            $criteria->compare('path', $className, true);
            $criteria->compare('widget_id', $this->Widget->id);
            $model = CmsWidgetLayout::model()->find($criteria);
            if (is_object($model))
            {
                Yii::import($model->path);
                $this->_wl = new $className($this);
            }
        }
        return $this->_wl;
    }
    
    /**
    * @return ContentType
    */
    public function getContentType()
    {
        if ($this->_contentType === null)
        {
            //TODO: need change model column -> path column
            $parentClass = get_parent_class($this);
            if (strpos($parentClass, 'ContentController') !== false)
            {
                //TODO: get content type path
                $model = new $parentClass(time());
                $this->_contentType = ContentType::model()->findByAttributes(array('path'=>$model->info['path']));
            }
        }
        return $this->_contentType;
    }
    
    protected function installContent()
    {
        $contentType = new ContentType;
        $contentType->attributes = $this->info;
        $contentType->criteria = var_export(array(),true);
        $contentType->status = true;
        $contentType->creation_datetime = $contentType->last_update = date('Y-m-d H:i:s');
        if (!$contentType->save())
        {
            Yii::log(CVarDumper::dumpAsString($contentType->getErrors()), CLogger::LEVEL_ERROR);
        }
    }
    
    protected function uninstallContent()
    {
        ContentType::model()->deleteAllByAttributes(array('path'=>$this->info['path']));
    }
    
    protected function installWidget()
    {
        $widget = $this->getWidget();
        if (is_object($widget))
            return false;
        $widget = new CmsWidget;
        $widget->attributes = $this->info;
        $widget->status = true;
        if ($widget->save())
        {
            //insert default settings
            $defaultConfig = $this->getDefaultConfig();
            foreach ($defaultConfig as $name => $config)
            {
                $model = new WidgetSetting;
                $model->label = $config['label'];
                $model->value = $config['value'];
                $model->description = $config['description'];
                $model->setting_group = $config['setting_group'];
                $model->visible = $config['visible'];
                $model->name = $name;
                $model->widget_id = $widget->id;
                if (!$model->save())
                {
                    Yii::log(CVarDumper::dumpAsString($model->getErrors()), CLogger::LEVEL_ERROR, 'CmsWidget.install');
                }
            }
            //insert default layouts
            if (isset($defaultConfig['currentLayout'], $defaultConfig['currentLayout']['items']) && is_array($defaultConfig['currentLayout']['items']) && count($defaultConfig['currentLayout']['items']))
            {
                foreach ($defaultConfig['currentLayout']['items'] as $key => $name)
                {
                    //TODO: detect widget layout location
                    $className = str_replace('Controller', '', get_class($this)).ucfirst($key).'Layout';
                    $className = Yii::import($this->getModule()->getId().'.layouts.'.$className, true);
                    /** @var WidgetLayoutBase */
                    $layout = new $className($widget);
                    $layout->install();
                }
            }
        }
    }
    
    protected function uninstallWidget()
    {
        $widget = $this->getWidget();
        if (is_object($widget))
        {
            //uninstall widget settings
            WidgetSetting::model()->deleteAllByAttributes(array('widget_id'=>$widget->id));
            //uninstall layouts
            $layouts = CmsWidgetLayout::model()->findAllByAttributes(array('widget_id'=>$widget->id));
            CmsWidgetLayout::model()->deleteAllByAttributes(array('widget_id'=>$widget->id));
            if (is_array($layouts))
            {
                $layouts = CHtml::listData($layouts, 'id', 'id');
                $criteria = new CDbCriteria;
                $criteria->addInCondition('widget_layout_id', $layouts);
                WidgetLayoutSetting::model()->deleteAll($criteria);
            }
            
            $widget->delete();
        }
    }
    
    protected function getFormParams()
    {
        $params = array();
        $widget = $this->getWidget();
        if (is_object($widget))
            $params = $widget->params;
            
        //load widget_settings from page_widget
        if (is_object(self::$pageWidget))
        {
            foreach ($params as $index => $param)
            {
                if (isset($this->WidgetSettings[$param->name]))
                {
                    $params[$index]->value = $this->WidgetSettings[$param->name]['value'];
                }
            }
        }
        
        return $this->createWidget('Admin.components.ParamForm',array(
            'params' => $params,
            'config' => $this->WidgetSettings,
        ));
    }
    
    protected function getFormLayoutParams()
    {
        $widgetLayout = $this->getWidgetLayout();
        if (!is_object($widgetLayout))
            throw new CException('Invalid widget layout');
        $params = array();
        $criteria = new CDbCriteria;
        $criteria->with = array('params');
        $criteria->compare('path', $widgetLayout->info['path']);
        $model = CmsWidgetLayout::model()->find($criteria);
        if (is_object($model))
            $params = $model->params;
        //CVarDumper::dump($model->params);exit;
            
        //load widget_settings from page_widget
        if (is_object(self::$pageWidget))
        {
            foreach ($params as $index => $param)
            {
                if (isset($widgetLayout->ConfigParams[$param->name]))
                {
                    $params[$index]->value = $widgetLayout->ConfigParams[$param->name]['value'];
                }
            }
        }
        
        return $this->createWidget('Admin.components.ParamForm',array(
            'params' => $params,
            'config' => $widgetLayout->ConfigParams,
        ));
    }
    
    protected function widgetConfig()
    {
        $formParams = $this->getFormParams();
        $formLayoutParams = $this->getFormLayoutParams();
            
        if (Yii::app()->request->IsPostRequest)
        {
            $formParams->saveParams($_POST);
            $formLayoutParams->saveParams($_POST);
            $this->refresh();
        }
        
        $content = '<div class="form wide">';
        $content .= $this->widget('CmsWidgetForm', array(
            'formParams'=>$formParams,
            'formLayoutParams'=>$formLayoutParams,
        ), true);
        $content .= '</div>';
        $this->renderText($content);
    }
}
